package com.ymttest.utils;

import org.springframework.stereotype.Component;

import com.ymt.core.tool.Logger;
import com.ymt.core.tool.RSAUtils;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;


/**
 * Created by wangxudong on 2017/8/31.
 */
@Component
public class BaofooSignature {

    /** 1024bit 加密块 大小 */
    public final static int ENCRYPT_KEYSIZE = 117;
    /** 1024bit 解密块 大小 */
    public final static int DECRYPT_KEYSIZE = 128;

    /**
     * Mock 公钥
     */
    private final String mockPublicKey =
            "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDmP+e7IKiIxxGYzYZl5S2qbmCbkgAjeM81mgwp7owBHdncbpcaee2o65zYFI0SXJuzu5rZBe3BPLucuZeg3t7FjNf2C7j8gfDYcviMamOwI7VuWZ+ZEtCHSHkOhUlwcul5xLMXl2nPd1YzL6zMCe2VAK75cHoBKnd+DmEVSOQipQIDAQAB";
    /**
     * Mock 支付宝私钥
     */
    private final String mockYmtPrivateKey =
            "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOY/57sgqIjHEZjNhmXlLapuYJuSACN4zzWaDCnujAEd2dxulxp57ajrnNgUjRJcm7O7mtkF7cE8u5y5l6De3sWM1/YLuPyB8Nhy+IxqY7AjtW5Zn5kS0IdIeQ6FSXBy6XnEsxeXac93VjMvrMwJ7ZUArvlwegEqd34OYRVI5CKlAgMBAAECgYBApPCKuUCYJkvqesmhEhcgIp09EGC5lNGYWwfPPgpQxfDE0sfZxyHSq1P91sdEwHt2mtV+2QtHlaWW+wR3RhuFEuGM1z8fsvongAk9bNDPvaPz07HF1YwXuviakDYk1bWwqCS+9VFJ82fGae4+ftUQOmJYSH+LV89RRqWdCP5GgQJBAP/nwVbgw/bBR04UDfUK2Bdr+Op+6WFdFoyzK7Kvr5sjO0T5ewswHJ34+B26X50kGqkIU2h2AXh8/AX1ZJUB5vsCQQDmVbglUXIrjLG5zraxstNlDnJvDL3WmYtZJxbKWq9QgSWYzf4iCaAVqsjZHfAHAV2iMGf+x55QGuHk7hZ0SGrfAkEAlVRE0xCX6c8BcANt3Zc1X/2GpDfosgMjHHmVP1Eb1RirBmXasj2iBWD6UEaocsdVs1uDaIqr8wZj/ooi5nzUrwJBAM5R2jETU4FO9aPKVju2Q0UyO67dau7fesLREMkRkhg6lsLZQdqbZJoD8QUKnAaqYoT1dzHw/Q4kBlRaMCLY+2ECQQDVAbyCAAte4LH9EndxkisOZXKMLbjhlmORpyKBUwSwW6Hk4If4hlKTIOUCuwXJzb08BK40AGD+pw6P35e+B3Dh";



    /**
     * 加密数据
     * @param privateKeyText
     * @param rawData 原始数据
     * @return
     */
    public String encryptData(String rawData){
        try {
            PrivateKey privateKey = RSAUtils.loadPrivateKey(EnvSetup.getData("privateK"));
            String base64str = base64Encode(rawData);
            byte[] bytes = base64str.getBytes("UTF-8");
            byte[] destBytes = rsaByKey(bytes, privateKey, Cipher.ENCRYPT_MODE);

            Logger.debug("baofoo rsa encryptData, rawData:"+rawData);

            String encString = byte2Hex(destBytes);
            return encString;

        } catch (Exception e) {
        	Logger.debug("baofoo rsa encryptData failed, with:" + rawData);
        }
        return null;
    }

    /**
     * 解密数据
     * @param publicKeyText
     * @param encData 加密数据
     * @return
     * @throws Exception 
     */
    public String decryptData(String encData) throws Exception{
        PublicKey publicKey = RSAUtils.loadPublicKey(EnvSetup.getData("publicK"));

        byte[] decode = hex2Bytes(encData);
        byte[] destBytes = null;
        try {
            destBytes = rsaByKey(decode, publicKey, Cipher.DECRYPT_MODE);
            String destString = new String(destBytes, "UTF-8");
            String rawString = base64Decode(destString);

            Logger.debug("baofoo rsa decryptData success,rawString:{}"+rawString);

            return rawString;
        } catch (Exception e) {
        	Logger.debug("baofoo rsa decryptData failed, with:" + encData);
        }
		return null;
    }

    /**
     * 将byte[] 转换成字符串
     */
    public static String byte2Hex(byte[] srcBytes) {
        StringBuilder hexRetSB = new StringBuilder();
        for (byte b : srcBytes) {
            String hexString = Integer.toHexString(0x00ff & b);
            hexRetSB.append(hexString.length() == 1 ? 0 : "").append(hexString);
        }
        return hexRetSB.toString();
    }

    /**
     * 将16进制字符串转为转换成字符串
     */
    public static byte[] hex2Bytes(String source) {
        byte[] sourceBytes = new byte[source.length() / 2];
        for (int i = 0; i < sourceBytes.length; i++) {
            sourceBytes[i] = (byte) Integer.parseInt(source.substring(i * 2, i * 2 + 2), 16);
        }
        return sourceBytes;
    }



    /**
     * 私钥算法
     *
     * @param srcData
     *            源字节
     * @param privateKey
     *            私钥
     * @param mode
     *            加密 OR 解密
     * @return
     */
    public byte[] rsaByKey(byte[] srcData, Key privateKey, int mode) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(mode, privateKey);
        // 分段加密
        int blockSize = (mode == Cipher.ENCRYPT_MODE) ? ENCRYPT_KEYSIZE : DECRYPT_KEYSIZE;
        byte[] decryptData = null;

        for (int i = 0; i < srcData.length; i += blockSize) {
            byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));

            decryptData = addAll(decryptData, doFinal);
        }
        return decryptData;
    }

    public byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
        if (array == null) {
            return null;
        }
        if (startIndexInclusive < 0) {
            startIndexInclusive = 0;
        }
        if (endIndexExclusive > array.length) {
            endIndexExclusive = array.length;
        }
        int newSize = endIndexExclusive - startIndexInclusive;

        if (newSize <= 0) {
            return new byte[0];
        }

        byte[] subarray = new byte[newSize];

        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);

        return subarray;
    }

    public byte[] addAll(byte[] array1, byte[] array2) {
        if (array1 == null) {
            return clone(array2);
        } else if (array2 == null) {
            return clone(array1);
        }
        byte[] joinedArray = new byte[array1.length + array2.length];
        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
        return joinedArray;
    }

    public byte[] clone(byte[] array) {
        if (array == null) {
            return null;
        }
        return (byte[]) array.clone();
    }

    /**
     * Base64加密
     */
    public String base64Encode(String str) throws UnsupportedEncodingException {
        return new String(new Base64().encode(str.getBytes("UTF-8")));
    }

    /**
     * 解密
     */
    public String base64Decode(String str) throws UnsupportedEncodingException, IOException {
        return new String(new Base64().decode(str), "UTF-8");
    }
}
